Skip to content

Comments

refactor(Android, Tabs): Appearance refactor on Android#3672

Open
t0maboro wants to merge 24 commits intomainfrom
@t0maboro/appearance-api-android-2
Open

refactor(Android, Tabs): Appearance refactor on Android#3672
t0maboro wants to merge 24 commits intomainfrom
@t0maboro/appearance-api-android-2

Conversation

@t0maboro
Copy link
Contributor

@t0maboro t0maboro commented Feb 20, 2026

Description

This PR introduces a refactor of the Android tabs appearance configuration into a more structured and explicit form.

The goal of this change is to:

  • Align the Android API more closely with the iOS implementation
  • Make appearance configuration more predictable

Structured Appearance Model

The appearance configuration for Android tabs has been reorganized into clearly separated sections, describing different aspects of TabBar:

  • backgroundColor
  • itemRippleColor
  • labelVisibilityMode
  • itemColors (normal / selected / focused / disabled)
  • activeIndicator
  • typography
  • badge

Each part (colors, typography, badge, etc.) is now explicitly grouped in dedicated interfaces.


From now on, the appearance of the entire tab bar on Android is determined by the currently active Screen, the same way it is handled on iOS.

This means:

  • The active screen fully controls the tab bar appearance.
  • When the active screen changes, the tab bar appearance updates accordingly.

Notes on Dynamic Updates

While the API allows updating appearance dynamically, some properties can negatively affect layout when changed drastically at runtime.

In particular:

  • labelVisibilityMode
  • activeIndicator.enabled
  • typography props

Changing these props dynamically may:

  • Trigger layout recalculations
  • Cause visible layout glitches
  • Lead to janky or unstable UI transitions

For this reason, it is not recommended to change these properties aggressively at runtime. They should be treated as relatively stable configuration options.

Closes: https://github.com/software-mansion/react-native-screens-labs/issues/955

Changes

  • Renamed classes: AppearanceApplicator & AppearanceCoordinator are now less coupled with the Host component, as they depend on the selected Screen, either. Therefore, I decided to remove "Host" from the names of these classes.
  • Diffing mechanism before applying tab bar appearance updates was added. This will prevent assigning the same values multiple times if a specific prop remains unchanged.
  • ColorsStateLists were extended to support focused and disabled states - parity with UIAppearance states from UIKit.
  • New TabsAppearanceModel was defined.
  • Old way of passing all props as top-level props was replaced with passing appearance config object from JS. This is a breaking change that will be hidden behing the compatibility flag.
  • All native prop "legacy" setters were replaced with the specific parser for Appearance object.
  • Appearance configuration was moved from Host to Screen.

Before & after - visual documentation

This PR unlocks some new behaviors, not sure if Before section is needed, as for Tab 1 & Tab 4 - the flow remains unchanged. For Tab2 & Tab3 - I'm adding new features for configuring TabBar appearance, which are covered in After video

After

after.mov

Test plan

Updated TestBottomTabs example to match the new API structure.

Checklist

  • Included code example that can be used to test this change.
  • Updated / created local changelog entries in relevant test files.
  • For visual changes, included screenshots / GIFs / recordings documenting the change.
  • For API changes, updated relevant public types.
  • Ensured that CI passes

@t0maboro t0maboro marked this pull request as ready for review February 23, 2026 12:22
@t0maboro t0maboro changed the title WIP - Appearance refactor on Android refactor(Android, Tabs): Appearance refactor on Android Feb 23, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the Android tabs appearance configuration API from a flat, host-level prop structure to a more structured, screen-level appearance object. The change aligns the Android API more closely with the iOS implementation by moving appearance control from the TabsHost to individual TabScreen components, allowing each screen to define how the tab bar should appear when that screen is active.

Changes:

  • Introduced structured AndroidTabsAppearance type with nested interfaces for different appearance aspects (colors, typography, badge, activeIndicator)
  • Moved appearance configuration from TabsHost props to TabScreen.standardAppearanceAndroid prop
  • Implemented diffing mechanism in TabsAppearanceApplicator to prevent redundant UI updates
  • Added compatibility flag usesRefactoredTabsAppearanceApiAndroid for downstream library detection

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/flags.ts Added compatibility flag for the refactored Android tabs appearance API
src/fabric/bottom-tabs/BottomTabsScreenNativeComponent.ts Added Android appearance types and standardAppearanceAndroid prop; removed legacy badge color props
src/fabric/bottom-tabs/BottomTabsNativeComponent.ts Removed all legacy Android-specific appearance props from TabsHost
src/components/tabs/TabsScreen.types.ts Added new structured Android appearance types with comprehensive documentation; moved TabBarItemLabelVisibilityMode from TabsHost
src/components/tabs/TabsScreen.tsx Added mapper functions to convert public API types to native prop format with proper color processing
src/components/tabs/TabsHost.types.ts Removed all Android appearance props and unnecessary imports
apps/src/tests/issue-tests/TestBottomTabs/index.tsx Updated test to use new screen-level appearance API instead of host-level props
android/.../RNSBottomTabsScreenManagerInterface.java Replaced badge color setters with standardAppearanceAndroid setter
android/.../RNSBottomTabsScreenManagerDelegate.java Updated prop handling to use standardAppearanceAndroid instead of individual badge color props
android/.../RNSBottomTabsManagerInterface.java Removed all Android appearance prop setters from host manager interface
android/.../RNSBottomTabsManagerDelegate.java Removed all Android appearance prop case handlers from host manager delegate
android/.../TabsHostViewManager.kt Removed all @ReactProp methods for Android appearance configuration
android/.../TabsHost.kt Removed appearance-related observable properties; made currentFocusedTab internal; renamed coordinator; added onAppearanceChanged callback
android/.../TabsAppearanceModel.kt New file defining internal data classes for Android tabs appearance structure
android/.../TabsAppearanceCoordinator.kt Renamed from TabsHostAppearanceCoordinator; updated to use appearance from current focused tab
android/.../TabsAppearanceApplicator.kt New file replacing TabsHostAppearanceApplicator with diffing mechanism for all appearance properties
android/.../TabScreenViewManager.kt Added parser for standardAppearanceAndroid prop with helper functions for safe type extraction; removed badge color prop setters
android/.../TabScreenDelegate.kt Added onAppearanceChanged callback interface
android/.../TabScreen.kt Added appearance property with change observer; removed badge color properties

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* appearance props for Tabs on Android. To allow backward compatibility,
* we expose a way to check whether the new implementation is in use or not.
*/
usesRefactoredTabsAppearanceApiAndroid: true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: maybe it should be coordinated with #3633 and hidden behind a single compat. flag?

@t0maboro t0maboro force-pushed the @t0maboro/appearance-api-android-2 branch from abc0830 to 4434a66 Compare February 23, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant